package com.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.entity.DStockProfile;
import com.entity.DStockTradeAvg;
import com.entity.DStockTradeDaily2025;
import com.entity.DStockTradeToday;
import com.entity.dto.GPDto;
import com.mapper.db4.DStockTradeDaily2025Mapper;
import com.server.IDStockProfileService;
import com.server.IDStockTradeAvgService;
import com.server.IDStockTradeDaily2025Service;
import com.server.IDStockTradeTodayService;
import com.util.ColltionUtils;
import com.util.DateUtils;
import com.util.Response;
import com.util.StringUtil;
import com.util.httpUtil.HttpUtils;
import com.util.thread.ThreadPoolUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/GP")
@Api(tags = "股票请求", value = "节点请求类")
public class GPController {


    @Autowired
    private IDStockProfileService idStockProfileService;

    @Autowired
    private IDStockTradeDaily2025Service daily2025Service;

    @Autowired
    private IDStockTradeTodayService todayService;

    @Autowired
    private IDStockTradeAvgService idStockTradeAvgService;

    @Autowired
    private DStockTradeDaily2025Mapper dStockTradeDaily2025Mapper;

    private static String token = "a6fb845695c9490e67998d82b0bd53ef6947b02b117194c4a9a9b607";
    private static String 股票列表 = "stock_basic";
    private static String 股票列表入参 = "ts_code,symbol,name,area,industry,list_date,market";

    private static String 股票日K详情 = "daily";
    private static String 股票日K详情出参顺序 = "ts_code,start_date,end_date,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount";

    // 单次最大可提取6000条数据
    private static String 股票实时日K = "rt_k";

    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 保存股票基本信息
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/saveGP")
    @ApiOperation(value = "保存股票")
    public Response saveGP(@RequestBody GPDto gpDto) throws IOException {


        String url = "http://api.tushare.pro";
        Map map = new HashMap<>();
        map.put("api_name", 股票列表);
        map.put("token", token);
        Map params = new HashMap<>();
        params.put("list_stauts", "L");
        map.put("params", params);
        map.put("fields", 股票列表入参);
        String posturlcontent = null;
        try {
             posturlcontent = HttpUtils.doPost(url, map);
        } catch (Exception e) {
            e.printStackTrace();
        }

//        posturlcontent = FileUtils.readJson("D:\\response2.json");

        Map parse = JSON.parseObject(posturlcontent, Map.class);
        Object code = parse.get("code");
        if (!code.equals(0)) {
            return Response.createError(parse.get("msg").toString());
        }
        Object data = parse.get("data");
        Map respData = JSON.parseObject(JSON.toJSONString(data), Map.class);
        Object respList = respData.get("items");
        List<ArrayList> arrayLists = JSON.parseArray(JSON.toJSONString(respList), ArrayList.class);

        List<DStockProfile> dStockProfiles = new ArrayList<>();
        arrayLists.forEach(arrayList -> {
            DStockProfile dStockProfile = new DStockProfile();
            dStockProfile.setTsCode(arrayList.get(0).toString());
            dStockProfile.setSymbol(arrayList.get(1).toString());
            dStockProfile.setName(arrayList.get(2).toString());
            dStockProfile.setArea(arrayList.get(3).toString());
            dStockProfile.setIndustry(arrayList.get(4).toString());
            dStockProfile.setListDate(arrayList.get(5).toString());
            dStockProfile.setMarket(arrayList.get(6).toString());
            dStockProfiles.add(dStockProfile);

        });
        idStockProfileService.remove(new LambdaQueryWrapper<>());
        log.info("保存股票数据为：" + dStockProfiles.size());

        List<List<DStockProfile>> lists = ColltionUtils.splitList(dStockProfiles, 5000);
        for (List<DStockProfile> listList : lists) {
            ThreadPoolUtils.dataMigrateExecutor.execute(() -> {
                idStockProfileService.saveBatch(listList);
            });
        }

        return Response.createSuccess("成功");
    }


    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 保存股票历史日k
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/saveDay")
    @ApiOperation(value = "保存股票历史日k")
    public Response saveDay(@RequestBody GPDto gpDto) {
        /*
        接口：daily，可以通过数据工具调试和查看数据
        数据说明：交易日每天15点～16点之间入库。本接口是未复权行情，停牌期间不提供数据
        调取说明：120积分每分钟内最多调取500次，每次6000条数据，相当于单次提取23年历史
        */

        List<DStockProfile> dStockProfileList = idStockProfileService.list();
        String url = "http://api.tushare.pro";
        Map map = new HashMap<>();

        map.put("token", token);
        Map params = new HashMap<>();


        // 历史区间时间
        map.put("api_name", 股票日K详情);


        // 同步当天数据不需要切割
        int num = 1000;
        if (StringUtil.isEmpty(gpDto.getTradeDate())) {
            num = 35;
            params.put("start_date", gpDto.getStartDate());
            params.put("end_date", gpDto.getEndDate());
        }else{
//            Date date = new Date();
//            String format = DateUtils.format(date, "yyyy-MM-dd");
            params.put("trade_date", gpDto.getTradeDate());
        }

        int total = 0;
        List<List<DStockProfile>> dsList = ColltionUtils.splitList(dStockProfileList, num);
        for (List<DStockProfile> dStockProfileList1 : dsList) {
            String tsCodeStr = dStockProfileList1.stream().map(DStockProfile::getTsCode).collect(Collectors.joining(","));
            params.put("ts_code", tsCodeStr);
            map.put("params", params);
            String posturlcontent = null;
            try {
                posturlcontent = HttpUtils.doPost(url, map);
            } catch (Exception e) {
                e.printStackTrace();
            }

            Map parse = JSON.parseObject(posturlcontent, Map.class);
            Object code = parse.get("code");
            if (!code.equals(0)) {
                return Response.createError(parse.get("msg").toString());
            }
            Object data = parse.get("data");
            Map respData = JSON.parseObject(JSON.toJSONString(data), Map.class);
            Object respList = respData.get("items");
            List<ArrayList> arrayLists = JSON.parseArray(JSON.toJSONString(respList), ArrayList.class);


            // 历史数据
            List<DStockTradeDaily2025> dStockProfiles = new ArrayList<>();
            arrayLists.forEach(arrayList -> {
                DStockTradeDaily2025 tradeDaily2025 = new DStockTradeDaily2025();
                tradeDaily2025.setTsCode(arrayList.get(0).toString());
                tradeDaily2025.setTradeDate(arrayList.get(1).toString());
                tradeDaily2025.setOpen(Float.valueOf(arrayList.get(2).toString()));
                tradeDaily2025.setHigh(Float.valueOf(arrayList.get(3).toString()));
                tradeDaily2025.setLow(Float.valueOf(arrayList.get(4).toString()));
                tradeDaily2025.setClose(Float.valueOf(arrayList.get(5).toString()));
                tradeDaily2025.setPreClose(Float.valueOf(arrayList.get(6).toString()));
                tradeDaily2025.setChange(Float.valueOf(arrayList.get(7).toString()));
                tradeDaily2025.setPctChg(Float.valueOf(arrayList.get(8).toString()));
                tradeDaily2025.setVol(Double.valueOf(arrayList.get(9).toString()));
                tradeDaily2025.setAmount(Double.valueOf(arrayList.get(10).toString()));
                dStockProfiles.add(tradeDaily2025);

            });

            total = total + dStockProfiles.size();
            List<List<DStockTradeDaily2025>> lists = ColltionUtils.splitList(dStockProfiles, 5000);
            for (List<DStockTradeDaily2025> listList : lists) {
                ThreadPoolUtils.dataMigrateExecutor.execute(() -> {
                    daily2025Service.saveBatch(listList);
                });
            }
        }

        log.info("保存股票数据为：" + total);
        return Response.createSuccess("成功");
    }



    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 保存股票实时日k
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/selectTime")
    @ApiOperation(value = "保存股票实时日k")
    public Response selectTime(@RequestBody GPDto gpDto) {

        /*
            接口：rt_k
            描述：获取实时日k线行情，支持按股票代码及股票代码通配符一次性提取全部股票实时日k线行情
            限量：单次最大可提取6000条数据
        */

        List<DStockProfile> dStockProfileList = idStockProfileService.list();
        String tsCodeStr = dStockProfileList.stream().map(DStockProfile::getTsCode).collect(Collectors.joining(","));
        String url = "http://api.tushare.pro";
        Map map = new HashMap<>();
        map.put("api_name", 股票实时日K);
        map.put("token", token);

        /**
         *  fields为返回字段
         *  默认返回字段：["ts_code", "name", "pre_close", "high", "open", "low", "close", "vol", "amount", "num"]
         *  额外字段      ask_volume1    委托卖盘（股）
         *              bid_volume1     委托买盘（股）
          */


        map.put("fields", Arrays.asList("ts_code", "name", "pre_close", "high", "open", "low", "close", "vol", "amount", "num"));
        Map params = new HashMap<>();
        // 支持通配符方式，e.g. 6*.SH、301*.SZ、600000.SH ; '3*.SZ,6*.SH,0*.SZ,9*.BJ'; '3*.SZ,600000.SH,000001.SZ'
        // 全部 "3*.SZ,6*.SH,0*.SZ,9*.BJ"
        params.put("ts_code", tsCodeStr);
        map.put("params", params);

        String posturlcontent = null;
        try {
            posturlcontent = HttpUtils.doPost(url, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
//        posturlcontent = FileUtils.readJson("D:\\sad.json");
        Map parse = JSON.parseObject(posturlcontent, Map.class);
        Object code = parse.get("code");
        if (!code.equals(0)) {
            return Response.createError(parse.get("msg").toString());
        }
        Object data = parse.get("data");
        Map respData = JSON.parseObject(JSON.toJSONString(data), Map.class);
        Object respList = respData.get("items");
        List<ArrayList> arrayLists = JSON.parseArray(JSON.toJSONString(respList), ArrayList.class);


        // 实时数据
        List<DStockTradeToday> dStockTradeTodays = new ArrayList<>();
        arrayLists.forEach(arrayList -> {
            DStockTradeToday tradeToday = new DStockTradeToday();
            tradeToday.setTsCode(arrayList.get(0).toString());
            tradeToday.setName(arrayList.get(1).toString());
            tradeToday.setPreClose(Float.valueOf(arrayList.get(2).toString()));
            tradeToday.setHigh(Float.valueOf(arrayList.get(3).toString()));
            tradeToday.setOpen(Float.valueOf(arrayList.get(4).toString()));
            tradeToday.setLow(Float.valueOf(arrayList.get(5).toString()));
            tradeToday.setClosee(Float.valueOf(arrayList.get(6).toString()));
            tradeToday.setVol(Double.valueOf(arrayList.get(7).toString()));
            tradeToday.setAmount(Double.valueOf(arrayList.get(8).toString()));
            tradeToday.setNum(Integer.valueOf(arrayList.get(9).toString()));

            // 额外数据
            if ((arrayList.size() > 10)) {
                tradeToday.setAskVolume1(Integer.valueOf(arrayList.get(10).toString()));
            }
            if (arrayList.size() > 11) {
                tradeToday.setBidVolume1(Integer.valueOf(arrayList.get(11).toString()));
            }
            // 当日时间
            tradeToday.setTradeDate(DateUtils.format(new Date(), "yyyyMMdd"));
            dStockTradeTodays.add(tradeToday);

        });

        // 删除历史数据
        todayService.remove(new LambdaQueryWrapper<>());

        log.info("保存股票数据为：" + dStockTradeTodays.size());
        List<List<DStockTradeToday>> lists = ColltionUtils.splitList(dStockTradeTodays, 5000);
        for (List<DStockTradeToday> listList : lists) {
            ThreadPoolUtils.dataMigrateExecutor.execute(() -> {
                todayService.saveBatch(listList);
            });
        }


        return Response.createSuccess("成功");
    }

    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 获取符合模型一： 前4个月高点低于今日收盘价，前一个月最低点与前4个月高点浮动超过20%，且今日收盘价不高于最高点5%
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/getGP")
    @ApiOperation(value = "获取超过近几个月最高点，且近一个月超过20%的股票")
    public Response getGP(@RequestBody GPDto gpDto) throws IOException {

        Date date = new Date();
        Date datestart = DateUtils.addDay(date, -120);
        Date dateEnd = DateUtils.addDay(date, -30);
        // 时间区间最大收盘价
        List<DStockTradeDaily2025> dStockTradeDaily2025s = daily2025Service.maxValue(DateUtils.format(datestart, "yyyyMMdd"), DateUtils.format(dateEnd, "yyyyMMdd"));

        // 时间区间最小收盘价
        Date datestart2 = DateUtils.addDay(date, -30);
        Date dateEnd2 = DateUtils.addDay(date, -20);
        List<DStockTradeDaily2025> minValue = daily2025Service.minValue(DateUtils.format(datestart2, "yyyyMMdd"), DateUtils.format(dateEnd2, "yyyyMMdd"));




        List<DStockTradeToday> todayList = new ArrayList<>();
        // 今日数据
        List<DStockTradeToday> list = todayService.list();

        for (DStockTradeToday tradeToday : list) {
            for (DStockTradeDaily2025 dStockTradeDaily2025 : dStockTradeDaily2025s) {

                if (tradeToday.getTsCode().equals(dStockTradeDaily2025.getTsCode())) {
                    Float close = tradeToday.getClosee();

                    Float close1 = dStockTradeDaily2025.getClose();

                    if (close > close1) {
                        // 涨幅百分比 有精度丢失
                        float v1 = (close - close1) / close *100;
                        if (v1 < 3) {
                            DStockTradeToday dStockTradeToday = new DStockTradeToday();
                            dStockTradeToday.setTsCode(tradeToday.getTsCode());
                            dStockTradeToday.setName(tradeToday.getName());
                            dStockTradeToday.setClosee(dStockTradeDaily2025.getClose());
                            todayList.add(dStockTradeToday);
                        }

                    }

                }
            }
        }


        List<DStockTradeToday> returnData = new ArrayList<>();

        for (DStockTradeToday tradeToday : todayList) {
            for (DStockTradeDaily2025 dStockTradeDaily2025 : minValue) {
                if (tradeToday.getTsCode().equals(dStockTradeDaily2025.getTsCode())) {
                    Float close = tradeToday.getClosee();
                    Float close1 = dStockTradeDaily2025.getClose();

                    // 最高价与最低价的跌幅 跌幅大于20%
                    float v1 = (close - close1) / close * 100;
                    if (v1 > 20) {
                        DStockTradeToday dStockTradeToday = new DStockTradeToday();
                        dStockTradeToday.setTsCode(tradeToday.getTsCode());
                        dStockTradeToday.setName(tradeToday.getName());
                        System.out.println(JSON.toJSON(dStockTradeToday));
                        returnData.add(dStockTradeToday);
                    }
                }
            }
        }

        log.info("分析完的股票数量为：" + returnData.size());
        return Response.createSuccess(returnData);

    }


    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 获取符合模型2：
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/getGP2")
    @ApiOperation(value = "模型二：近一个月跌幅大于20%，且今日收盘价大于昨日收盘价5%区间内")
    public Response getGP2(@RequestBody GPDto gpDto) throws IOException {
        Date date = new Date();

        // 时间区间最小收盘价
        Date datestart = DateUtils.addDay(date, -30);
        Date dateEnd = DateUtils.addDay(date, -10);
        List<DStockTradeDaily2025> minValue = daily2025Service.minValue(DateUtils.format(datestart, "yyyyMMdd"), DateUtils.format(dateEnd, "yyyyMMdd"));


        // 今日数据
        List<DStockTradeToday> list = todayService.list();

        List<DStockTradeToday> todayList = new ArrayList<>();
        for (DStockTradeToday tradeToday : list) {
            for (DStockTradeDaily2025 dStockTradeDaily2025 : minValue) {

                if (tradeToday.getTsCode().equals(dStockTradeDaily2025.getTsCode())) {
                    Float close = tradeToday.getClosee();

                    Float close1 = dStockTradeDaily2025.getClose();

                    if (close > close1) {
                        // 涨幅百分比 有精度丢失
                        float v1 = (close - close1) / close *100;
                        if (v1 > 10) {
                            // 今日收盘价是昨天收盘价涨幅5%以内,并且今天收盘价大于昨天收盘价
                            if (close > tradeToday.getPreClose()) {
                                float v2 = (close - tradeToday.getPreClose()) / close *100;
                                if (v2 < 5 ) {
                                    DStockTradeToday dStockTradeToday = new DStockTradeToday();
                                    dStockTradeToday.setTsCode(tradeToday.getTsCode());
                                    dStockTradeToday.setName(tradeToday.getName());
                                    dStockTradeToday.setClosee(dStockTradeDaily2025.getClose());
                                    todayList.add(dStockTradeToday);

                                }
                            }


                        }

                    }

                }
            }
        }


        log.info("模型2分析完的股票数量为：" + todayList.size());
        return Response.createSuccess(todayList, Long.valueOf(todayList.size()));
    }


    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 获取符合模型3：
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/getGP3")
    @ApiOperation(value = "获取符合刚上5日均线股票列表")
    public Response getGP3(@RequestBody GPDto gpDto) throws IOException {
        // 今日数据
        List<DStockTradeToday> list = todayService.list();

        List<DStockTradeAvg> avgList = idStockTradeAvgService.list(new LambdaQueryWrapper<DStockTradeAvg>().eq(DStockTradeAvg::getTradeDate, "20250527"));
        Map<String, List<DStockTradeAvg>> collect = avgList.stream().collect(Collectors.groupingBy(DStockTradeAvg::getTsCode));

        List<DStockTradeToday> todayList = new ArrayList<>();
        for (DStockTradeToday dStockTradeToday : list) {
            String tsCode = dStockTradeToday.getTsCode();
            List<DStockTradeAvg> avgList1 = collect.get(tsCode);
            Double avg5 = avgList1.get(0).getAvg5();
            Float closee = dStockTradeToday.getClosee();
            if (closee > avg5) {
                double v2 = (Double.valueOf(closee) - avg5) / closee *100;
                if (v2 < 5  && v2 >2) {
                    todayList.add(dStockTradeToday);
                }
            }

        }
        log.info("获取符合刚上5日均线股票列表：" + todayList.size());
        return Response.createSuccess(todayList);
    }

    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 获取符合模型4
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/getGP4")
    @ApiOperation(value = "跌幅超过30%，今日价最高最低点均高于昨日最高最低点")
    public Response getGP4(@RequestBody GPDto gpDto) throws IOException {


        // 时间区间最大收盘价
        List<DStockTradeDaily2025> dStockTradeDaily2025s = daily2025Service.maxValue(gpDto.getStartDate(), gpDto.getEndDate());

        // 时间区间最小收盘价
//        Date date = new Date();
//        Date datestart = DateUtils.addDay(date, -30);
//        Date dateEnd = DateUtils.addDay(date, -10);
        List<DStockTradeDaily2025> minValue = daily2025Service.minValue(gpDto.getStartDate(), gpDto.getEndDate());

        // 返回数据
        List<DStockTradeToday> todayList = new ArrayList<>();

        // 今日数据
        List<DStockTradeToday> list = todayService.list();
        Map<String, List<DStockTradeToday>> collect = list.stream().collect(Collectors.groupingBy(DStockTradeToday::getTsCode));
        for (DStockTradeDaily2025 maxTradeDaily : dStockTradeDaily2025s) {
            for (DStockTradeDaily2025 mibTradeDaily : minValue) {
                if (maxTradeDaily.getTsCode().equals(mibTradeDaily.getTsCode())) {
                    Float close = maxTradeDaily.getClose();

                    Float close1 = mibTradeDaily.getClose();

                    if (close > close1) {
                        // 涨幅百分比 有精度丢失
                        float v1 = (close - close1) / close * 100;
                        if (v1 > 30) {
                            if (CollectionUtils.isNotEmpty(collect.get(maxTradeDaily.getTsCode()))) {

                                DStockTradeToday dStockTradeToday = collect.get(maxTradeDaily.getTsCode()).get(0);
                                Float closee1 = dStockTradeToday.getClosee();
                                Float closee = dStockTradeToday.getPreClose();
                                if (closee1 > closee) {
                                    double v2 = (closee1 - closee) / closee * 100;
                                    if (v2 < 3 && v2 > 1) {
                                        todayList.add(dStockTradeToday);
                                    }
                                }

                            }
                        }

                    }

                }

            }

        }

        log.info("获取符合刚上5日均线股票列表：" + todayList.size());
        return Response.createSuccess(todayList);
    }



    /**
     * @param gpDto tTreeNodeReq
     * @return response response
     * @Description 清洗均线数据入库
     * @Author chl
     * @Date 19:19 2021/12/20
     **/
    @PostMapping("/saveAvgData")
    @ApiOperation(value = "保存平均K线数据")
    public Response saveAvgData(@RequestBody GPDto gpDto) throws IOException {
        daily2025Service.saveAvgData();


        return Response.createSuccess();
    }
    public static void main(String[] args) {
        Float close = 30f;

        Float close1 = 20f;
        float v1 = (close - close1) / close *100;

        System.out.println(v1);
        if (v1<10) {
        }

    }


}
